﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;

namespace GRMS.App_Code
{
    public class ActionEventRequest
    {
        #region Properties
        public string SkillCheck;
        public string MinSkillCheck;
        public List<string> Targets;
        public string Actor;
        public string MainType;
        public string SubType;
        public Dictionary<string, string> Attributes;
        #endregion
    }

    public class ActionEvent
    {
        #region Properties
        public ActionEventRequest Request;
        public List<string> Script;
        #endregion

        #region Constructors
        public ActionEvent(ActionEventRequest request, List<string> script)
        {
            this.Request = request;
            this.Script = script;
        }
        #endregion
    }

    public class ActionEventFactory
    {
        #region Properties
        private Session current;
        private ActionEventLibrary AEL;
        #endregion

        #region Constructors
        public ActionEventFactory(Session current)
        {
            this.current = current;
            this.AEL = new ActionEventLibrary("/App_Data/Rules/ActionEventLibrary.xml", this.current);
        }
        #endregion

        #region Methods
        public ActionEvent GenerateActionEvent(ActionEventRequest aer)
        {
            string action;
            string diff;
            List<string> customCommands = CommonCommands.GetCustomCommandList(current);

            switch(aer.MainType)
            {
                case "Initiative":
                    action = AEL.GetActionEventDefination("Initiative");
                    break;
                case "Resistance":
                case "Athletics":
                case "Dodge":
                    action = AEL.GetActionEventDefination("Resistance");
                    break;
                case "Damage":
                    action = AEL.GetActionEventDefination("Damage");
                    break;
                case "combat":
                case "checkless":
                    action = AEL.GetActionEventDefination(aer.SubType);
                    break;
                default:
                    if (aer.Targets.Count < 1)
                        action = AEL.GetActionEventDefination("UnopposedCheck");
                    else
                        action = AEL.GetActionEventDefination("OpposedCheck");
                    break;
            }

            //ToDo: Process Targets
            if (action.Contains("{TargetCode}"))
            {
                string actionDef = action.Clone().ToString();
                string actionList = "";

                foreach (string target in aer.Targets)
                {
                    action = actionDef;

                    foreach (string cmd in customCommands)
                        action = action.Replace("{" + cmd + "}", CommonCommands.GetCustomCommand(cmd, current));

                    action = action.Replace("{SkillCheck}", aer.SkillCheck);
                    action = action.Replace("{MinSkillCheck}", aer.MinSkillCheck);
                    action = action.Replace("{Actor}", aer.Actor);
                    action = action.Replace("{MainType}", aer.MainType);
                    action = action.Replace("{SubType}", aer.SubType);

                    if (aer.Attributes != null && aer.Attributes.Count != 0)
                        foreach (KeyValuePair<string, string> kvp in aer.Attributes)
                            action = action.Replace(kvp.Key, kvp.Value);

                    if (action.Contains("{Target_GetDifficulity({Target})}"))
                    {
                        //diff = "8";
                        diff = Target_GetDifficulity(target, current);
                        action = action.Replace("{Difficulty}", diff);
                        action = action.Replace("{Target_GetDifficulity({Target})};", "");
                    }

                    action = action.Replace("{Target}", target).Replace("{TargetCode}", "");

                    actionList += action;
                }

                action = actionList;
            }
            else
            {
                foreach (string cmd in customCommands)
                    action = action.Replace("{" + cmd + "}", CommonCommands.GetCustomCommand(cmd, current));

                action = action.Replace("{SkillCheck}", aer.SkillCheck);
                action = action.Replace("{MinSkillCheck}", aer.MinSkillCheck);
                action = action.Replace("{Actor}", aer.Actor);
                action = action.Replace("{MainType}", aer.MainType);
                action = action.Replace("{SubType}", aer.SubType);

                if (aer.Attributes != null && aer.Attributes.Count != 0)
                    foreach (KeyValuePair<string, string> kvp in aer.Attributes)
                        action = action.Replace(kvp.Key, kvp.Value);

                //ToDo: Process GM Interaction
                if (action.Contains("{GM_GetDifficulity()}"))
                {
                    //GM_GetDifficulity(aer.Actor, aer.MainType, aer.SubType);
                    diff = "8";
                    action = action.Replace("{Difficulty}", diff);
                    action = action.Replace("{GM_GetDifficulity()};", "");
                }
            }

            char[] seperator = { ';' };
            ActionEvent ae = new ActionEvent(aer, new List<string>(action.Split(seperator, StringSplitOptions.RemoveEmptyEntries)));

            for (int i = 0; i < ae.Script.Count; i++)
            {
                ae.Script[i] = ae.Script[i].Trim();
            }
            ae.Script.RemoveAt(ae.Script.Count - 1);

            return ae;
        }

        private string Target_GetDifficulity(string target, Session sesh)
        {
            ActionEventFactory AEF = new ActionEventFactory(sesh);
            ActionEventHandler AEH = new ActionEventHandler(sesh);
            string Defense = "";

            if (((ActionSequencer)sesh.GetGlobal("CombatList")).CurrentActor() != target)
            {
                string[] defense = { "Dodge", "Athletics", "Resistance" };
                Dictionary<string, string> dict = sesh.GetCharacter(target).GetActions("combat", "");
                foreach (string s in defense)
                    if (dict.ContainsKey(s))
                    {
                        Defense = s;
                        break;
                    }
            }
            else
                Defense = "Resistance";
            ActionEventRequest AER = sesh.GetCharacter(target).GetEventRequest(Defense);
            ActionEvent AE = AEF.GenerateActionEvent(AER);

            return AEH.ProcessActionEvent(AE).Replace("<br/>", "");
        }
        #endregion
    }
}
